package utils

import (
	"crypto/aes"
	"crypto/sha1"
	"encoding/base64"
	"errors"
	"strings"

	"gitee.com/sansaniot/ssiot-core/logger"
)

const aesRuleCode = "hongdian_license"

//加密
func EncryptAES(srcStr string) string {
	//明文处理
	srcByte := []byte(srcStr)
	//密钥处理
	keyByte := []byte(aesRuleCode)
	//加密处理
	src, err := aesEncryptECB(srcByte, keyByte)
	//判断是否成功
	if err == nil {
		return base64.StdEncoding.EncodeToString(src)
	} else {
		//日志
		logger.Errorf("aes加密失败 src=[+%v] err=[%+v]", srcStr, err)
		return ""
	}
}

//解密
func DecryptAES(srcStr string) string {
	//处理(gin框架在处理请求参数携带+ 会被转化为空格 所以这个位置要还原 否则解密失败)
	srcStr = strings.ReplaceAll(srcStr, " ", "+")
	//明文处理
	srcByte, _ := base64.StdEncoding.DecodeString(srcStr)
	//密钥处理
	keyByte := []byte(aesRuleCode)
	//解密处理
	src, err := aesDecryptECB(srcByte, keyByte)
	//判断是否成功
	if err == nil {
		return string(src)
	} else {
		//日志
		logger.Errorf("aes解密失败 src=[+%v] err=[%+v]", srcStr, err)
		return ""
	}
}

//128位 随机数加密 aes
func aesEncryptECB(src []byte, key []byte) ([]byte, error) {
	// 比示例一多出这一步
	key, err := aesSha1prng(key, 128)
	if err != nil {
		return nil, err
	}

	cipher, _ := aes.NewCipher(generateKey(key))
	length := (len(src) + aes.BlockSize) / aes.BlockSize
	plain := make([]byte, length*aes.BlockSize)
	copy(plain, src)
	pad := byte(len(plain) - len(src))
	for i := len(src); i < len(plain); i++ {
		plain[i] = pad
	}
	encrypted := make([]byte, len(plain))
	// 分组分块加密
	for bs, be := 0, cipher.BlockSize(); bs <= len(src); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
		cipher.Encrypt(encrypted[bs:be], plain[bs:be])
	}

	return encrypted, nil
}

func aesDecryptECB(encrypted []byte, key []byte) ([]byte, error) {
	key, err := aesSha1prng(key, 128) // 比示例一多出这一步
	if err != nil {
		return nil, err
	}

	cipher, _ := aes.NewCipher(generateKey(key))
	decrypted := make([]byte, len(encrypted))
	//
	for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
		cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
	}

	trim := 0
	if len(decrypted) > 0 {
		trim = len(decrypted) - int(decrypted[len(decrypted)-1])
	}

	return decrypted[:trim], nil
}

// 模拟 java SHA1PRNG 处理
func aesSha1prng(keyBytes []byte, encryptLength int) ([]byte, error) {
	hashs := sha1prng(sha1prng(keyBytes))
	maxLen := len(hashs)
	realLen := encryptLength / 8
	if realLen > maxLen {
		return nil, errors.New("invalid length!")
	}
	return hashs[0:realLen], nil
}
func sha1prng(data []byte) []byte {
	h := sha1.New()
	h.Write(data)
	return h.Sum(nil)
}
func generateKey(key []byte) (genKey []byte) {
	genKey = make([]byte, 16)
	copy(genKey, key)
	for i := 16; i < len(key); {
		for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 {
			genKey[j] ^= key[i]
		}
	}
	return genKey
}
